/************************************************************************************************
 *   深圳市摩西尔电子有限公司 @版本所有@
 *
 *   此文件用于控件接口
 *
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 巫昭雯
 *      时间 : 2019.11.8
 *      内容 : 所有代码
 *************************************************************************************************/

/*exported mc_ui_item_grp */
/*global mc_sdk_param */
/*global mc_ui_lab */
/*global mc_ui_edit */
/*global mc_ui_step */
/*global mc_ui_select */
/*global mc_ui_slider */
/*global mc_ui_checkbox */
/*global mc_ui_radio */
/*global mc_ui_select_file */
/*global mc_param_val_txt_to_rgb */
/*global mc_param_val_rgb_to_txt */
/*global $ */

var g_ary_item_grp_json = [];

function mc_ui_item_val_change(id, val) {
    for (var json_jdx = 0; json_jdx < g_ary_item_grp_json.length; json_jdx++) {
        if (g_ary_item_grp_json[json_jdx] instanceof mc_ui_item_grp) {
            if (g_ary_item_grp_json[json_jdx].dom_val_chg(id, val)) {
                return true;
            }
        }
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    控件对象
 * 功能:
 *    根据提供的json数组生成控件列表
 * 参数:
 *    NA
 * 返回：
 *    NA
 * 例子：
 *    NA
 * 备注：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 巫昭雯
 *      时间 : 2019.11.8
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_ui_item_grp() {
    var m_obj_param_rsp = new mc_sdk_param();
    // 建立dom_id和name_id关联的对象;key=PARAM NAME_ID, value=param_key_item_pair struct
    var m_obj_domid_param_map = {};
    // 默认列数
    var ui_col_cnt_def = 3;
    // 返回的控件dom
    var str_dom_html = "";
    // 语言表数组对象
    var m_obj_lang_data = {};
    // 存储控件合并模式的对象
    var obj_combo_mode_def = {};
    // 判断该控件组是否都存在尾部标签
    var b_item_tail = false;

    // 定义常量:可选属性
    var c_attr_val_array = "ARRAY";
    var c_attr_val_tail_id = "TAIL_ID_LIST";
    var c_attr_val_switch_text = "SWITCH_TEXT";
    var c_attr_val_mult_file = "MULT_FILE";

    // 可选属性有 VAL_TYPE | DESCRIPT_ID |  MIN_VAL | MAX_VAL  |ARRAY | STEP | TAIL_ID_LIST | ENABLE | MULT_FILE | EXT_NAME | SHOW_VAL(强制显示值)
    // 定义常量:可选参数属性对象{ key:可选参数：方法名}
    var obj_attr_opt = {
        VAL_TYPE: "set_type",
        DESCRIPT_ID: "set_title",
        MIN_VAL: "set_min_val",
        MAX_VAL: "set_max_val",
        STEP: "set_step_val",
        ARRAY: "set_arr",
        SWITCH_TEXT: "set_text",
        ENABLE: "set_enable",
        MULT_FILE: "set_mult_file",
        EXT_NAME: "set_accept",
        SHOW_VAL: "set_show_val"
    };
    // 定义常量:可选参数属性对象{ key:可选参数：方法名};更新dom时调用的方法
    var obj_attr_opt_dom = {
        VAL_TYPE: "set_dom_type",
        DESCRIPT_ID: "set_dom_title",
        MIN_VAL: "set_dom_min_val",
        MAX_VAL: "set_dom_max_val",
        STEP: "set_dom_step_val",
        ARRAY: "set_dom_arr",
        SWITCH_TEXT: "set_dom_text",
        ENABLE: "set_dom_enable",
        MULT_FILE: "set_dom_mult_file",
        EXT_NAME: "set_dom_accept"
    };

    // 判断是否是混合合并
    var b_item_mix_combo_mode = false;
    // 控件组全为合并模式下&&一行存放的最大列数为一列时---> 设置最小宽度为混合合并模式的宽度
    var b_all_combo_mode_to_mix_mode = false;
    // 定义控件尾部单位长度
    var str_item_tail_width = "";
    // 控件rgb不合并下的同步控制按钮
    var b_ctrl_btn = false;
    var arr_ctrl_text = ["MC_LANG_LINK", "OFF"];   //eslint-disable-line
    var m_ui_ctrl_btn_id = 0;

    // register instance to globle array
    g_ary_item_grp_json.push(this);


    /************************************************************************************************
     * 类型:
     *    控件对象函数
     * 功能:
     *    生成控件对象,建立关联;
     * 参数:
     *    NA
     * 返回：
     *    NA
     * 例子：
     *    NA
     * 备注：
     *    item_title:控件标签名
     *    item_val:控件本省对象;长度为1 : 合并模式;长度为3: 不合并模式  R=0/G=1/B=2
     *    item_tail:控件尾部单位
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function param_key_item_pair() {
        this.item_title = null;
        // item_val : length === 1,use combo mode, other used R=0/G=1/B=2 mode
        this.item_val = [];
        this.item_tail = null;
        this.item_ctrl_btn = null;
    }

    // 数据变动回调
    this.on_val_chg = null;

    // 控件的类型
    var arr_item_type = {
        EDIT: mc_ui_edit,
        STEP_EDIT: mc_ui_step,
        OPTION: mc_ui_select,
        SLIDER: mc_ui_slider,
        TOGGLE: mc_ui_checkbox,
        LABEL: mc_ui_lab,
        RADIO: mc_ui_radio,
        FILE_SELECTOR: mc_ui_select_file
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    根据ui_type值创造不同的实例对象函数
     * 参数:
     *    @param { Promise<String> } val ui_type值;
     * 返回：
     *    @returns { Promise<Object> } 返回需要创建的对象实例
     *    @returns { Promise<Boolean> } false:执行不成功;未找到相应的对象
     * 例子：
     *    NA
     * 备注：
     *    目前ui_type值以下几种
     *       EDIT: 编辑框,
     *       STEP_EDIT: 步进编辑框,
     *       OPTION: 下拉列表框,
     *       SLIDER: 滑动条,
     *       TOGGLE: 复选框,
     *       LABEL: 标签,
     *       RADIO: 单选按钮组,
     *       FILE_SELECTOR:文件选择器
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function new_ui_type_fun(val) {
        if ("undefined" !== typeof val) {
            if (Object.prototype.hasOwnProperty.call(arr_item_type, val)) {
                return new arr_item_type[val]();
            }
        }
        return false;
    }

    // 获取控件类型
    this.get_ui_type = function () {
        return arr_item_type;
    };


    /************************************************************************************************
     * 类型:
     *   函数
     * 功能:
     *   界面控件值变动时触发事件
     * 参数:
     *    @param { Promise<String> } str_id 控件的id值;
     *    @param { Promise<String> } str_val 控件选中的value值;
     * 返回：
     *    @returns { Promise<Boolean> } true === 执行成功 || false === 数据格式不正确或是不存在未选中数据;
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.dom_val_chg = function (str_id, str_val) {
        if ("string" !== typeof str_id || 0 === str_id.length || "undefined" === typeof str_val) {
            return false;
        }

        var ary_key = Object.keys(m_obj_domid_param_map);

        for (var idx_key = 0; idx_key < ary_key.length; idx_key++) {
            var str_param_name_id = ary_key[idx_key];
            var item_grp = m_obj_domid_param_map[str_param_name_id];
            var obj_ctrl_btn = item_grp.item_ctrl_btn;

            for (var idx_val = 0; idx_val < item_grp.item_val.length; idx_val++) {
                var item = item_grp.item_val[idx_val];

                if (!Object.prototype.hasOwnProperty.call(item, "get_id")) {
                    continue;
                }

                if (item.get_id() !== str_id) {
                    continue;
                }

                var str_ui_type = m_obj_param_rsp.get_attr_val(str_param_name_id, "UI_TYPE");
                // old json value
                var str_saved_val_txt = m_obj_param_rsp.get_param_value(str_param_name_id);
                // old dom value
                var str_save_dom_val = JSON.parse(JSON.stringify(str_val));


                // 设置布尔值：0表示false;其他表示true
                if ("TOGGLE" === str_ui_type && "boolean" === typeof str_val) {
                    switch (str_val) {
                    case false:
                        str_val = "0";
                        break;
                    default:
                        str_val = "1";
                        break;
                    }
                }

                // 处理文件选择器数据
                if ("FILE_SELECTOR" === str_ui_type) {
                    var str_val_type = m_obj_param_rsp.get_attr_val(str_param_name_id, "VAL_TYPE");
                    var arr_val = str_val.slice(0);

                    // constructor format
                    var obj_format_val_type = new format_data_arr_str();
                    var obj_format_ext = new format_data_arr_str();

                    obj_format_val_type.set_separator("\r\n");
                    obj_format_ext.set_key_name("file_extension");

                    if ("FILE_NAME" === str_val_type) {
                        obj_format_val_type.set_key_name("file_name");
                    } else {
                        obj_format_val_type.set_key_name("hexdata");
                    }

                    // 设置json串value值
                    str_val = obj_format_val_type.to_str(arr_val);

                    // 设置json串属性EXT_NAME值
                    m_obj_param_rsp.set_attr_val(str_param_name_id, "EXT_NAME", obj_format_ext.to_str(arr_val));
                }


                // new value
                var str_new_val = str_val;

                if (1 < item_grp.item_val.length) {
                    var ary_rgb_val = mc_param_val_txt_to_rgb(str_saved_val_txt);

                    if (3 > idx_val) {
                        ary_rgb_val[idx_val] = str_val;

                        // need link
                        // if (need_rgb_val_same(obj_ctrl_btn)) {
                        if (obj_ctrl_btn && obj_ctrl_btn.get_val()) {
                            ary_rgb_val = [str_val, str_val, str_val];
                            set_item_dom_val_link(item_grp.item_val, str_save_dom_val);
                        }
                    }
                    str_new_val = mc_param_val_rgb_to_txt(ary_rgb_val);
                }

                if (str_saved_val_txt === str_new_val) {
                    return true;
                }

                m_obj_param_rsp.set_param_value(str_param_name_id, str_new_val);

                if ("function" === typeof this.on_val_chg) {
                    this.on_val_chg(str_param_name_id, str_new_val);
                }

                return true;
            }
        }

        return false;
    };

    /************************************************************************************************
     * 类型:
     *    获取语言表函数
     * 功能:
     *    生成控件对象,建立关联;
     * 参数:
     *    @param { Promise<String> } str_key 语言表key;name_id
     * 返回：
     *    @returns { Promise<String> } 根据语言表对比获取的对应中英文
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function get_lang_trans(str_key) {
        if ("string" !== typeof str_key || 0 === str_key.length) {
            return "";
        }

        var str_ret_val = m_obj_lang_data[str_key.toLocaleUpperCase()];

        if ("string" !== typeof str_ret_val || 0 === str_ret_val.length) {
            return str_key;
        }

        // return str_ret_val;
        return str_key;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置value值为rgb格式
     * 参数:
     *    @param { Promise<String> } val 控件的value值;
     * 返回：
     *    @returns { Promise<Array> } 转换成数组
     * 例子：
     *    参数:"1"
     *    返回: ["1","1","1"]
     *    参数:"R=1,G=2,B=3"
     *    返回: ["1","2","3"]
     * 备注：
     *    若参数为RGB形式的字符串,返回的数组则为将RGB值取出来组成的数组;
     *    若参数为单个字符串值,返回的数组每个值相同;
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_val_rgb(val) {
        var val_split = val;
        var arr_val_rgb = [];

        for (var idx = 0; 3 > idx; idx++) {
            if (-1 !== val.indexOf("=")) {
                val_split = val.split(",");
                arr_val_rgb.push(val_split[idx].slice(2));
            } else {
                arr_val_rgb.push(val_split);
            }
        }
        return arr_val_rgb;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置value值的类型为布尔格式
     * 参数:
     *    @param { Promise<Array> } arr 数组值
     * 返回：
     *    @returns { Promise<Array> } 将数组里面的值转化为布尔类型;
     * 例子：
     *    参数:["1","1","0"]
     *    返回:[true,true,false]
     * 备注：
     *    数据值转换规则："0" === false || 其他 === true;
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_val_type_to_boolean(arr) {
        var b_val = [true, true, true];

        for (var idx = 0; idx < arr.length; idx++) {
            if ("0" === arr[idx]) {
                b_val[idx] = false;
            }
        }

        return b_val;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    处理下拉列表数据
     * 参数:
     *    @param { Promise<String> } str 下拉列表值;
     * 返回：
     *    @returns { Promise<Array> } 转换成数组
     * 例子：
     *    参数:"0=FPGA,1=T6"
     *    返回: ["FPGA","T6"]
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function deal_arr_opt_data(str) {
        var arr_val_new = [];
        var arr_split = str.split(",");

        for (var idx_val = 0; idx_val < arr_split.length; idx_val++) {
            var str_val = arr_split[idx_val];

            if ("" === str_val.trim()) {
                continue;
            }

            var str_txt = str_val;
            var i_gap_pos = str_val.indexOf("=");

            if (1 <= i_gap_pos) {
                str_val = str_val.substr(0, i_gap_pos);
                str_txt = str_txt.substr(i_gap_pos + 1);
            }
            str_val = str_val.trim();
            str_txt = str_txt.trim();
            if (0 === str_txt.length) {
                str_txt = str_val;
            }
            str_txt = get_lang_trans(str_txt);

            arr_val_new.push(str_val + "=" + str_txt);
        }

        return arr_val_new;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    控制列样式
     * 参数:
     *    @param { Promise<Number> } col_num 设置列数;
     * 返回：
     *    @returns { Promise<String> } 相应的列数应该相应的样式名
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_ui_clo_class(col_num) {
        var str_class = "";

        switch (col_num) {
        case 1:
            str_class = " item_box_max_col_one";
            break;
        case 2:
            str_class = " item_box_max_col_two";
            break;
        case 3:
            str_class = " item_box_max_col_three";
            break;
        default:
            str_class = " item_box_max_col_three";
            break;
        }
        return str_class;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件尾部显示字串ID
     * 参数:
     *    @param { Promise<Object> } m_obj 解析数据对象
     *    @param { Promise<String> } name_id 属性值name_id;
     *    @param { Promise<Object> } obj_item 需要修改的控件对象;
     *    @param { Promise<String> } fun_name 控件调用的方法名
     * 返回：
     *    NA
     * 例子：
     *    NA
     * 备注：
     *    尾部字串id获取之后需要对照语言表翻译
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_item_tail_val(m_obj, name_id, obj_item, fun_name) {
        var str_attr_val_tail = m_obj.get_attr_val(name_id, c_attr_val_tail_id);

        if ("undefined" !== typeof str_attr_val_tail && " " !== str_attr_val_tail) {
            b_item_tail = true;
            var str_attr_tail_return = "";

            var ary_tail = str_attr_val_tail.split(",");

            for (var idx_tail = 0; idx_tail < ary_tail.length; idx_tail++) {
                str_attr_tail_return += get_lang_trans(ary_tail[idx_tail]);
            }

            obj_item[fun_name](str_attr_tail_return);
        }
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置可选参数属性值
     * 参数:
     *    @param { Promise<Object> } obj_param_rsp 解析json串数据对象
     *    @param { Promise<Boolean> } b_combo 是否合并
     *    @param { Promise<Object> } obj_opt 可选属性对象;
     *    @param { Promise<String> } str_param_name name_id;
     *    @param { Promise<Array> } obj_rgb_combo 控件合并或者不合并对象数组
     * 返回：
     *    NA
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_attr_opt(obj_param_rsp, b_combo, obj_opt, str_param_name, obj_rgb_combo) {
        var arr_attr_opt = Object.keys(obj_opt);

        for (var attr_dix = 0; attr_dix < arr_attr_opt.length; attr_dix++) {
            var str_attr_val = obj_param_rsp.get_attr_val(str_param_name, arr_attr_opt[attr_dix]);

            if ("undefined" !== typeof str_attr_val) {
                // 如果可选参数为数组的话,处理数组数据
                if (arr_attr_opt[attr_dix] === c_attr_val_array) {
                    str_attr_val = deal_arr_opt_data(str_attr_val);
                }

                // 如果可选参数为SWITCH_TEXT;数据转化实例 "yes,no" 转化为 [yes,no]
                if (arr_attr_opt[attr_dix] === c_attr_val_switch_text) {
                    if (-1 !== str_attr_val.indexOf(",")) {
                        str_attr_val = [str_attr_val.split(",")[0], str_attr_val.split(",")[1]];
                    }
                }

                // 如果可选参数为MULT_FILE;数据转化为boolean值
                if (arr_attr_opt[attr_dix] === c_attr_val_mult_file) {
                    if (0 !== Number(str_attr_val)) {
                        str_attr_val = true;
                    } else {
                        str_attr_val = false;
                    }
                }

                var fun_name = obj_opt[arr_attr_opt[attr_dix]];

                if (Object.prototype.hasOwnProperty.call(obj_rgb_combo[0], fun_name)) {
                    for (var idx = 0; idx < obj_rgb_combo.length; idx++) {
                        obj_rgb_combo[idx][fun_name](str_attr_val);
                    }
                }
            }
        }
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件的的value值
     * 参数:
     *    @param { Promise<String> } str_param_value 控件对象的value值
     *    @param { Promise<String> } str_ui_type_val ui_type的值
     *    @param { Promise<Array> } arr_item_rgb_obj 控件对象数组
     *    @param { Promise<String> } fun_name 控件调用的方法名
     * 返回：
     *    NA
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    function set_item_itself_val(str_param_value, str_ui_type_val, arr_item_rgb_obj, fun_name) {
        // 设置控件的的value值
        if ("undefined" !== typeof str_param_value) {
            // 如果设置的val值为标签控件，需要翻译
            if ("LABEL" === str_ui_type_val) {
                str_param_value = get_lang_trans(str_param_value);
            }

            // 先默认把值转换为RGB形式
            var str_param_value_rgb = set_val_rgb(str_param_value);

            // 把值转为布尔类型
            if ("TOGGLE" === str_ui_type_val) {
                str_param_value_rgb = set_val_type_to_boolean(str_param_value_rgb);
            }

            for (var ui_type_idx = 0; ui_type_idx < arr_item_rgb_obj.length; ui_type_idx++) {
                if (Object.prototype.hasOwnProperty.call(arr_item_rgb_obj[ui_type_idx], fun_name)) {
                    arr_item_rgb_obj[ui_type_idx][fun_name](str_param_value_rgb[ui_type_idx]);
                }
            }
        }
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取占位div字符串
     * 参数:
     *    @param { Promise<Number> } count 控件组个数;
     *    @param { Promise<String> } str_class 控件组每一项最外层盒子样式;
     * 返回：
     *    @returns { Promise<String> } 生成的占位divzi字符串
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2020.6.19
     *      内容 : 所有代码
     ************************************************************************************************/
    function get_item_placeholder_str(count, str_class) {
        if ("undefined" === typeof count) {
            return "";
        }
        // 占位div
        var item_placeholder_div = "<div id='placeholder_div' class='placeholder_div " + str_class + "'></div>";

        // 计算占位div个数；
        var ui_pdiv_num = ui_col_cnt_def - (count % ui_col_cnt_def);
        var srt_html = "";

        // 判断是否需要占位div
        if (ui_pdiv_num !== ui_col_cnt_def) {
            for (var idx = 0; idx < ui_pdiv_num; idx++) {
                srt_html += item_placeholder_div;
            }
        }

        return srt_html;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件dom数据联动
     * 参数:
     *    @param { Promise<String> } arr_obj_item 内部保存的控件组对象数组；=== m_obj_domid_param_map 内保存的数据
     *    @param { Promise<String> } str_chg_val 单个控件数据变动回调返回的值; ===  on_val_chg 返回的值; 未转换之前的数据
     * 返回:
     *    @returns { Promise<Boolean> } true === 设置成功 || false === 设置失败或参数错误
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-12-10
     *       内容 : 所有代码
    ************************************************************************************************/
    function set_item_dom_val_link(arr_obj_item, str_chg_val) {
        if (!arr_obj_item) {
            return false;
        }

        if ("undefined" === typeof str_chg_val) {
            return false;
        }

        var ui_len = arr_obj_item.length;

        if (1 === ui_len) {
            return false;
        }

        for (var ui_i = 0; ui_i < ui_len; ui_i++) {
            var obj_i = arr_obj_item[ui_i];

            if (!obj_i) {
                continue;
            }

            if (!Object.prototype.hasOwnProperty.call(obj_i,"set_dom_val")) {
                continue;
            }

            obj_i.set_dom_val(str_chg_val);
        }

        return true;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取控制按钮类
     * 参数:
     *    NA
     * 返回:
     *    @returns { Promise<String> } "" || "mc_igp_has_btn" === 控件带有控制按钮
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-12-10
     *       内容 : 所有代码
    ************************************************************************************************/
    function get_ctrl_btn_class() {
        if (b_ctrl_btn) {
            return "mc_igp_has_btn";
        }

        return "";
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取合并模式下的控件类; 一些类特殊处理; mc_item_mix_combo_mode === 混合合并模式的类
     * 参数:
     *    NA
     * 返回:
     *    @returns { Promise<String> } 控件类
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-08-03
     *       内容 : 所有代码
    ************************************************************************************************/
    function get_combo_item_class() {
        var str_class = "";

        if (b_item_mix_combo_mode) {
            str_class += " mc_item_mix_combo_mode";
        } else {
            if (b_all_combo_mode_to_mix_mode && !b_item_tail) {
                str_class += " mc_item_mix_combo_mode";
            }
        }

        return str_class;
    }


    /************************************************************************************************
     * 类型:
     *    构造函数
     * 功能:
     *    联动控件
     * 参数:
     *    NA
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    条件 : 仅为混合模式 && 设置控件表示 === true && 该控件为不合并
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-06-07
     *       内容 : 所有代码
    ************************************************************************************************/
    function mc_ui_igp_link_btn() {
        this.id = "";
        this.get_html = function (b_combo) {
            if (b_ctrl_btn) {
                if (b_combo) {
                    return "<div class='mc_item_gp_ctrl_btn flex_box_horizontal'></div>";
                }

                // icon-connect icon-disconnect
                return "<div class='mc_item_gp_ctrl_btn flex_box_horizontal'><div id='" + this.get_id() + "' style='font-size:20px' class='btn_item btn_icon icon_btn icon-disconnect' lang_id='MC_LANG_LINK' >" + "</div></div>";
            }

            return "";
        };
        this.get_id = function () {
            m_ui_ctrl_btn_id++;
            var str_time = new Date().getTime() + (Math.random() * 1000).toFixed(0);
            var str_id = "mc_ui_igp_" + m_ui_ctrl_btn_id + "_" + str_time;

            this.id = str_id;
            return str_id;
        };
        // 获取当前联动值
        this.get_val = function () {
            var obj = document.getElementById(this.id);

            if (obj) {
                return $(obj).hasClass("is_link");
            }

            return false;
        };
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    初始化联动按钮事件
     * 参数:
     *    NA
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-06-07
     *       内容 : 所有代码
    ************************************************************************************************/
    this.init_link_btn_event = function () {
        $(".item_box .mc_item_gp_ctrl_btn .btn_item").each(function (idx, el) {  // eslint-disable-line
            this.onclick = function () {
                $(this).toggleClass("is_link icon-connect");
            };
        });
    };


    // **************************************** 接口 **************************************** //
    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置语言表
     * 参数:
     *    @param { Promise<Object> } obj_lang_map 语言表对象;
     * 返回：
     *    @returns { Promise<Boolean> } true === 设置成功  || false ===  参数类型错误或为空时
     * 例子：
     *    NA
     * 备注：
     *    可选属性有 VAL_TYPE | DESCRIPT_ID |  MIN_VAL | MAX_VAL  | ARRAY | STEP | ENABLE | MULT_FILE | EXT_NAME
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_lang_map = function (obj_lang_map) {
        if ("object" !== typeof obj_lang_map) {
            return false;
        }
        m_obj_lang_data = {};
        var ary_map = Object.keys(obj_lang_map);
        var ui_key_cnt = ary_map.length;

        for (var idx_key = 0; idx_key < ui_key_cnt; idx_key++) {
            var str_key = ary_map[idx_key];

            m_obj_lang_data[str_key.toUpperCase()] = obj_lang_map[str_key];
        }
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件json字串；判断数据生成的dom html字符串
     * 参数:
     *    @param { Promise<String> } str_json_txt 创建控件的JSON字串
     * 返回：
     *    @returns { Promise<Boolean> } true 设置成功 || false 参数类型错误或为空时
     * 例子：
     *    NA
     * 备注：
     *    1.输入的字符串参数需要调用mc_sdk_param接口转换成json对象
     *    2.处理的是输入的 PARAMS 参数
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_json_txt = function (str_json_txt) {
        if ("string" !== typeof str_json_txt) {
            return false;
        }

        m_obj_param_rsp.set_json(str_json_txt);
        var ui_param_cnt = m_obj_param_rsp.get_param_cnt();
        var ui_param_effective_cnt = ui_param_cnt;

        // 所有控件的组合html_dom列表
        var str_item_dom_list = "";

        // 控件组每一项最外层盒子样式
        var item_box_class = "item_box flex_box_horizontal " + set_ui_clo_class(ui_col_cnt_def) + " " + get_ctrl_btn_class();

        for (var item_idx = 0; item_idx < ui_param_cnt; item_idx++) {
            // 获取"NAME_ID" 和 VALUE
            var str_param_name = m_obj_param_rsp.get_param_name(item_idx);
            var str_param_value = m_obj_param_rsp.get_param_value(str_param_name);

            // 定义对象：控件前面部分对象(控件名)，控件本身对象，控件后面对象(单位)；一组控件控制按钮
            var obj_item_name_lable = new mc_ui_lab();
            var obj_item_unit_lable = new mc_ui_lab();
            var obj_item_ctrl_btn = new mc_ui_igp_link_btn();

            // 控件对象本省数组
            var arr_item_rgb_obj = [];

            // 获取param_name对应的语言表
            var str_param_name_trans = get_lang_trans(str_param_name);

            // 设置控件默认值,title值
            obj_item_name_lable.set_val(str_param_name_trans);
            obj_item_name_lable.set_title(str_param_name_trans);

            // 添加标签样式内容
            obj_item_name_lable.set_add_css("lable_margin_left item_gp_name");
            obj_item_unit_lable.set_add_css("lable_margin_left item_gp_unit");
            obj_item_unit_lable.set_style_width(str_item_tail_width);

            // ENABLE 属性
            var str_attr_enable = m_obj_param_rsp.get_attr_val(str_param_name, "ENABLE");
            // 获取属性为"UI_TYPE"的值;判断控件模式是否合并(默认不合并),创建相应的 判断控件类型对象
            var str_attr_ui_type_value = m_obj_param_rsp.get_attr_val(str_param_name, "UI_TYPE");

            if (!str_attr_ui_type_value || "0" === str_attr_enable) {
                ui_param_effective_cnt--;
                continue;
            }

            // 控件是否合并; 默认不合并
            var b_combo = "boolean" === typeof obj_combo_mode_def[str_param_name] ? obj_combo_mode_def[str_param_name] : false;

            // 创建控件对象
            if (b_combo) {
                arr_item_rgb_obj.push(new new_ui_type_fun(str_attr_ui_type_value));
            } else {
                for (var arr_obj_idx = 0; 3 > arr_obj_idx; arr_obj_idx++) {
                    arr_item_rgb_obj.push(new new_ui_type_fun(str_attr_ui_type_value));
                }
            }


            // 触发数据变动事件
            if (Object.prototype.hasOwnProperty.call(arr_item_rgb_obj[0], "on_val_chg")) {
                for (var arr_idx = 0; arr_idx < arr_item_rgb_obj.length; arr_idx++) {
                    arr_item_rgb_obj[arr_idx].on_val_chg = mc_ui_item_val_change;
                    // 若是显示芯片下拉框 开启分类选择下拉框
                    if ("MC_LANG_DISPCHIP_LIST" === str_param_name && "OPTION" === str_attr_ui_type_value) {
                        arr_item_rgb_obj[arr_idx].set_is_add_classify(true);
                    }
                }
            }

            //每一个返回的html标签：控件名，控件本身，控件单位
            var str_item_name = "";
            var str_item_itself = "";
            var str_item_tail = "";

            // 设置可选属性值： 可选属性有 VAL_TYPE | DESCRIPT_ID |  MIN_VAL | MAX_VAL  | ARRAY | STEP | TAIL_ID_LIST | ENABLE | MULT_FILE | EXT_NAME
            set_attr_opt(m_obj_param_rsp, b_combo, obj_attr_opt, str_param_name, arr_item_rgb_obj);

            // 设置控件的的value值
            set_item_itself_val(str_param_value, str_attr_ui_type_value, arr_item_rgb_obj, "set_val");

            // 控件尾部显示字串ID -- TAIL_ID_LIST
            set_item_tail_val(m_obj_param_rsp, str_param_name, obj_item_unit_lable, "set_val");

            // if (!b_item_tail) {
            //     // obj_item_unit_lable.set_add_css("hide_tail_lable");
            // }

            // 最后再设置dom
            str_item_name = obj_item_name_lable.get_html_txt();
            var item_class = "mc_item_combo flex_box_vertical";

            if (b_combo) {
                if (Object.prototype.hasOwnProperty.call(arr_item_rgb_obj[0], "get_html_txt")) {
                    str_item_itself = "<div class='" + item_class + get_combo_item_class() + "'>" + arr_item_rgb_obj[0].get_html_txt() + "</div>";
                }
            } else {
                for (var str_html_idx = 0; str_html_idx < arr_item_rgb_obj.length; str_html_idx++) {
                    if (Object.prototype.hasOwnProperty.call(arr_item_rgb_obj[str_html_idx], "get_html_txt")) {
                        str_item_itself += "<div class='mc_item_no_combo'>" + arr_item_rgb_obj[str_html_idx].get_html_txt() + "</div>";
                    }
                }
            }

            str_item_tail = obj_item_unit_lable.get_html_txt();

            // 建立对象和name_id 关联
            var obj_name_id_rela = new param_key_item_pair();

            obj_name_id_rela.item_title = obj_item_name_lable;
            obj_name_id_rela.item_tail = obj_item_unit_lable;
            obj_name_id_rela.item_val = [];

            if (b_ctrl_btn) {
                obj_name_id_rela.item_ctrl_btn = obj_item_ctrl_btn;
            }

            for (var name_id_rela_idx = 0; name_id_rela_idx < arr_item_rgb_obj.length; name_id_rela_idx++) {
                obj_name_id_rela.item_val.push(arr_item_rgb_obj[name_id_rela_idx]);
            }

            m_obj_domid_param_map[str_param_name] = obj_name_id_rela;

            var str_item_ctrl_btn = obj_item_ctrl_btn.get_html(b_combo);

            // 写入返回出去的html
            var item_html =
                "<div class='" + item_box_class + " '" + ">" +
                str_item_name +
                "<div class='flex_box_auto_size mc_igp_item_container mc_edt_inp_wrap'>" +
                str_item_itself +
                "</div>" +
                str_item_tail +
                str_item_ctrl_btn +
                "</div>";


            str_item_dom_list += item_html;
        }

        // 所有组件的组合赋值给定义的字符串dom,通过get_dom_html函数输出
        str_dom_html = str_item_dom_list + get_item_placeholder_str(ui_param_effective_cnt, item_box_class);
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    操纵dom更新数据
     * 参数:
     *    @param { Promise<String> } str_json_txt 更新后的数据字符串;
     * 返回：
     *   NA
     * 例子：
     *   NA
     * 备注：
     *   操作dom修改数据时控件需要调用dom的相应方法
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.update_dom_val = function (str_json_txt) {
        if ("string" !== typeof str_json_txt || 0 === str_json_txt.length) {
            return;
        }

        // 更新json串
        m_obj_param_rsp.set_json(str_json_txt);

        var obj_new_param = new mc_sdk_param();

        obj_new_param.set_json(str_json_txt);

        var ui_new_param_cnt = obj_new_param.get_param_cnt();

        for (var idx_new_param = 0; idx_new_param < ui_new_param_cnt; idx_new_param++) {
            var str_param_name_id = obj_new_param.get_param_name(idx_new_param);

            str_param_name_id = str_param_name_id.toUpperCase();
            if (!Object.prototype.hasOwnProperty.call(m_obj_domid_param_map, str_param_name_id)) {
                continue;
            }

            var obj_item_grp = m_obj_domid_param_map[str_param_name_id];

            var str_param_value = obj_new_param.get_param_value(str_param_name_id);

            // 设置控件头部标签
            obj_item_grp.item_title.set_dom_val(get_lang_trans(str_param_name_id));

            // 控件尾部显示字串ID
            set_item_tail_val(obj_new_param, str_param_name_id, obj_item_grp.item_tail, "set_dom_val");

            if (!b_item_tail) {
                // obj_item_grp.item_tail.set_add_css("hide_tail_lable");
            }

            // 合并模式
            var b_combo = false;

            if ("undefined" !== typeof obj_combo_mode_def[str_param_name_id]) {
                b_combo = obj_combo_mode_def[str_param_name_id];
            }

            // 设置可选属性
            set_attr_opt(obj_new_param, b_combo, obj_attr_opt_dom, str_param_name_id, obj_item_grp.item_val);

            // 设置控件的的value值
            set_item_itself_val(str_param_value, obj_new_param.get_attr_val(str_param_name_id, "UI_TYPE"), obj_item_grp.item_val, "set_dom_val");
        }
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置一行存放的控件列数
     * 参数:
     *    @param { Promise<number> } ui_col_cnt 一行存放的列数
     * 返回：
     *    @returns { Promise<Boolean> } true 设置成功  | false 参数类型错误或为空时
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_max_col_cnt = function (ui_col_cnt) {
        if ("number" !== typeof ui_col_cnt) {
            return false;
        }
        ui_col_cnt_def = ui_col_cnt;
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件尾部宽度
     * 参数:
     *    @param { Promise<String> } i_width 宽度值
     * 返回：
     *    @returns { Promise<Boolean> } true 设置成功  | false 参数类型错误或为空时
     * 例子：
     *    输入参数： "5px" || "10%"
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_item_unit_width = function (i_width) {
        if ("string" !== typeof i_width) {
            return false;
        }
        str_item_tail_width = i_width;
        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件里面的控件本身是否合并：根据RGB
     * 参数:
     *    @param { Promise<object> } obj_combo_mode 控件RGB对象
     * 返回：
     *    @returns { Promise<object> } true 设置成功  | false 参数类型错误或为空时
     * 例子：
     *    参数格式：
     *    key=ITEM_ID(NAME_ID), val=true/false
     *    var obj_combo_mode = {
     *     DISP_MODE: false,
     *     DATA_LEVEL_RATIO: false,
     *     PIX_OUTPUT_BIT_SIZE: true,
     *     PIX_INPUT_BIT_SIZE: true,
     *     DATA_LEVEL_OFFSET: false
     *    };
     * 备注：
     *    默认RGB不合并
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_rgb_combo_mode = function (obj_combo_mode) {
        if ("object" !== typeof obj_combo_mode) {
            return false;
        }
        obj_combo_mode_def = obj_combo_mode;

        var arr_combo_mode = Object.keys(obj_combo_mode_def);
        var arr_len = arr_combo_mode.length;

        for (var idx = 1; idx < arr_len; idx++) {
            if (obj_combo_mode_def[arr_combo_mode[idx]] !== obj_combo_mode_def[arr_combo_mode[0]]) {
                b_item_mix_combo_mode = true;
            }
        }

        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取生成的dom字符串
     * 参数:
     *    NA
     * 返回：
     *    @returns { Promise<string> } 返回生成的dom字符串
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.get_dom_html = function () {
        return str_dom_html;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取json字串
     * 参数:
     *    NA
     * 返回：
     *    @returns { Promise<string> } 返回当前对象的json字串数据
     * 例子：
     *    NA
     * 备注：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2019.11.8
     *      内容 : 所有代码
     ************************************************************************************************/
    this.get_json_txt = function () {
        return m_obj_param_rsp.get_json();
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置单项控件由全合并模式改为混合模式排列；
     *    相当与修改单项控件的宽度 === 混合模式下的单列宽度( mc_item_mix_combo_mode 类的宽度 )
     * 参数:
     *    @param { Promise<Boolean> } b 设置值 只接受布尔值;
     * 返回：
     *    @returns { Promise<Boolean> }  true === 设置成功 || false
     * 例子：
     *    NA
     * 备注：
     *    布局设置成功必要条件为： 尾部控件的值为空
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 巫昭雯
     *      时间 : 2020.6.19
     *      内容 : 所有代码
     ************************************************************************************************/
    this.set_item_all_combo_mode_to_mix_mode = function (b) {
        if ("boolean" !== typeof b) {
            return false;
        }

        b_all_combo_mode_to_mix_mode = b;

        return true;
    };

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置控件组是否构造控制按钮
     * 参数:
     *    @param { Promise<Boolean> } b 是否构造控制按钮； true === 创建 || false === 不创建(默认)
     *    NA
     * 返回:
     *    @returns { Promise<Boolean> } true === 设置成功 || false === 参数错误
     * 例子:
     *    NA
     * 备注:
     *    若使用联动按钮则在初始化布局之后需要调用 init_link_btn_event 接口
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-12-10
     *       内容 : 所有代码
    ************************************************************************************************/
    this.set_ctrl_btn = function (b) {
        if ("boolean" !== typeof b) {
            return false;
        }

        b_ctrl_btn = b;
        return true;
    };


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    设置联动按钮文本; 与 mc_ui_checkbox 控件set_text 方法一致; 当前只为转接口
     * 参数:
     *    @param { Promise<String> } val 参数与控件方法一致
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2021-04-21
     *       内容 : 所有代码
    ************************************************************************************************/
    this.set_ctrl_btn_text = function (val) {
        if ("undefined" === typeof val) {
            return;
        }

        arr_ctrl_text = val;
    };


    // **************************************** 格式化数据 **************************************** //
    /************************************************************************************************
     * 类型:
     *    构造函数
     * 功能:
     *    格式化数据 数组和字符串的转化
     * 参数:
     *    NA
     * 返回:
     *    NA
     * 例子:
     *    NA
     * 备注:
     *    NA
     * 修改:
     *    1. 类型 : 创建
     *       作者 : 巫昭雯
     *       时间 : 2020-08-07
     *       内容 : 所有代码
    ************************************************************************************************/
    function format_data_arr_str() {
        var key_name = "";
        // 分隔符
        var separator = ",";

        /************************************************************************************************
        * 类型:
        *    函数
        * 功能:
        *    设置分隔符
        * 参数:
        *    @param { Promise<String> } str 分隔符字符串
        * 返回:
        *    @returns { Boolean } 格式错误
        * 例子:
        *    NA
        * 备注:
        *    默认分隔符为逗号 ","
        * 修改:
        *    1. 类型 : 创建
        *       作者 : 巫昭雯
        *       时间 : 2020-08-07
        *       内容 : 所有代码
       ************************************************************************************************/
        this.set_separator = function (str) {
            if ("string" !== typeof str) {
                return false;
            }

            separator = str;
            return true;
        };

        /************************************************************************************************
         * 类型:
         *    函数
         * 功能:
         *    设置数组内的项的key值
         * 参数:
         *    @param { Promise<String> } key
         * 返回:
         *    @returns { Promise<Boolean> } 设置成功 || 参数格式错误
         * 例子:
         *    NA
         * 备注:
         *    NA
         * 修改:
         *    1. 类型 : 创建
         *       作者 : 巫昭雯
         *       时间 : 2020-08-07
         *       内容 : 所有代码
        ************************************************************************************************/
        this.set_key_name = function (key) {
            if ("string" !== typeof key) {
                return false;
            }

            key_name = key;
            return true;
        };


        /************************************************************************************************
         * 类型:
         *    函数
         * 功能:
         *    将选项转化为字符串
         * 参数:
         *    @param { Promise<String> } arr
         * 返回:
         *    @returns { Promise<String> } 返回转化后的字符串 || false
         * 例子:
         *    NA
         * 备注:
         *    NA
         * 修改:
         *    1. 类型 : 创建
         *       作者 : 巫昭雯
         *       时间 : 2020-08-07
         *       内容 : 所有代码
        ************************************************************************************************/
        this.to_str = function (arr) {
            if ("object" !== typeof arr && "[object Array]" !== Object.prototype.toString.call(arr)) {
                return false;
            }

            var str = "";
            var len = arr.length;

            for (var idx = 0; idx < len; idx++) {
                var item = arr[idx];

                if (item && item[key_name]) {
                    str += separator + item[key_name];
                }
            }

            var first = str.indexOf(separator);

            if (-1 !== first) {
                return str.substring(first + separator.length);
            }

            return str;
        };
    }
}


